home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
muds
/
pennmush.000
/
pennmush-1.50-p8-linux.tar
/
pennmush
/
set.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-04-06
|
26KB
|
1,049 lines
/* set.c */
#include "copyright.h"
/* commands which set parameters */
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include "config.h"
#include "db.h"
#include "match.h"
#include "interface.h"
#include "externs.h"
extern void set_flag(); /* from flags.c */
#ifdef NOCRYPT
char *crypt(s, t)
char *s, *t;
{
/* the DES encryption scheme cannot be exported outside the United States.
* Thus, this function is needed because the crypt() library function
* does not exist.
*/
return (s);
}
#endif
void do_name(player, name, newname)
dbref player;
const char *name;
char *newname;
{
dbref thing;
char *password;
#ifdef RWHO_SEND
char tbuf1[BUFFER_LEN];
#endif
if ((thing = match_controlled(player, name)) != NOTHING) {
/* check for bad name */
if (*newname == '\0') {
notify(player, "Give it what new name?");
return;
}
/* check for renaming a player */
if (Typeof(thing) == TYPE_PLAYER) {
#ifdef GUEST_RESTRICT
if (Guest(player)) {
notify(player, "Guests may not rename themselves.");
return;
}
#endif
/* split off password */
for (password = newname;
*password && !isspace(*password);
password++) ;
/* eat whitespace */
if (*password) {
*password++ = '\0'; /* terminate name */
while (*password && isspace(*password))
password++;
}
/* check for null password */
if (!*password) {
notify(player,
"You must specify a password to change a player name.");
notify(player, "E.g.: name player = newname password");
return;
} else if (!password_check(thing, password)) {
notify(player, "Incorrect password.");
return;
} else if (strcasecmp(newname, db[player].name)
&& !ok_player_name(newname)) {
/* strcasecmp allows changing foo to Foo, etc. */
notify(player, "You can't give a player that name.");
return;
}
/* everything ok, notify */
do_log(LT_CONN, 0, 0, "Name change by %s(#%d) to %s",
Name(thing), thing, newname);
fflush(connlog_fp);
if (Suspect(thing))
raw_broadcast(WIZARD, "Broadcast: Suspect %s changed name to %s.",
Name(thing), newname);
#ifdef RWHO_SEND
sprintf(tbuf1, "%d@%s", thing, MUDNAME);
rwhocli_userlogout(tbuf1);
#endif
delete_player(thing, NULL);
SET(Name(thing), newname);
add_player(thing, NULL);
#ifdef RWHO_SEND
rwhocli_userlogin(tbuf1, newname, time((time_t *) 0));
#endif
notify(player, "Name set.");
return;
} else {
if (!ok_name(newname)) {
notify(player, "That is not a reasonable name.");
return;
}
}
/* everything ok, change the name */
SET(Name(thing), newname);
notify(player, "Name set.");
}
}
static void do_alias(player, thing, attrib, alias)
dbref player;
dbref thing;
ATTR *attrib;
const char *alias;
{
/* Set the alias attribute on a player. A controls check has already
* been done.
*/
ATTR *temp;
char tbuf1[PLAYER_NAME_LIMIT];
if (Typeof(thing) != TYPE_PLAYER) {
/* The attribute doesn't do anything special. Just set it. */
atr_add(thing, attrib->name, alias, player, attrib->flags);
if (!Quiet(player) && !Quiet(thing))
notify(player, tprintf("%s - Set.", Name(thing)));
return;
}
if (*alias == '\0') {
/* Alias deletion. */
if ((temp = atr_get_noparent(thing, "ALIAS")) == NULL) {
notify(player, "No alias to remove.");
return;
} else {
strcpy(tbuf1, uncompress(temp->value));
delete_player(thing, tbuf1);
atr_add(thing, attrib->name, "", player, attrib->flags);
notify(player, "Alias removed.");
return;
}
}
if (!ok_player_name(alias)) {
notify(player, "That is not a valid alias.");
return;
}
if ((temp = atr_get_noparent(thing, "ALIAS")) != NULL) {
/* We have to delete the old alias before adding the new one. */
strcpy(tbuf1, uncompress(temp->value));
delete_player(thing, tbuf1);
}
/* Add the new alias. */
add_player(thing, alias);
atr_add(thing, attrib->name, alias, player, attrib->flags);
notify(player, "Alias set.");
}
void do_unlock(player, name, locktype)
dbref player;
const char *name;
int locktype;
{
dbref thing;
char *sp;
/* check for '@unlock <object>/<atr>' */
sp = (char *) index(name, '/');
if (sp) {
do_atrlock(player, name, "off");
return;
}
if ((thing = match_controlled(player, name)) != NOTHING) {
switch (locktype) {
case BASICLOCK:
free_boolexp(db[thing].key);
db[thing].key = TRUE_BOOLEXP;
break;
case USELOCK:
free_boolexp(db[thing].usekey);
db[thing].usekey = TRUE_BOOLEXP;
break;
case ENTERLOCK:
free_boolexp(db[thing].enterkey);
db[thing].enterkey = TRUE_BOOLEXP;
break;
}
notify(player, "Unlocked.");
}
}
void do_lock(player, name, keyname, locktype)
dbref player;
const char *name;
const char *keyname;
int locktype;
{
dbref thing;
struct boolexp *key;
char *sp;
if (!keyname || !*keyname) {
do_unlock(player, name, locktype);
return;
}
/* check for '@lock <object>/<atr>' */
sp = (char *) index(name, '/');
if (sp) {
do_atrlock(player, name, "on");
return;
}
init_match(player, name, NOTYPE);
match_everything();
switch (thing = match_result()) {
case NOTHING:
notify(player, "I don't see what you want to lock!");
return;
case AMBIGUOUS:
notify(player, "I don't know which one you want to lock!");
return;
default:
if (!controls(player, thing)) {
notify(player, "You can't lock that!");
return;
}
if (Flags(thing) & GOING) {
notify(player, "Why would you want to lock garbage?");
return;
}
break;
}
key = parse_boolexp(player, keyname);
/* do the lock */
if (key == TRUE_BOOLEXP) {
notify(player, "I don't understand that key.");
} else {
/* everything ok, do it */
switch (locktype) {
case BASICLOCK:
free_boolexp(db[thing].key);
db[thing].key = key;
break;
case USELOCK:
free_boolexp(db[thing].usekey);
db[thing].usekey = key;
break;
case ENTERLOCK:
free_boolexp(db[thing].enterkey);
db[thing].enterkey = key;
break;
}
notify(player, "Locked.");
}
}
void do_chown(player, name, newobj)
dbref player;
const char *name;
const char *newobj;
{
dbref thing;
dbref owner = NOTHING;
char *sp;
/* check for '@chown <object>/<atr>=<player>' */
sp = (char *) index(name, '/');
if (sp) {
do_atrchown(player, name, newobj);
return;
}
init_match(player, name, TYPE_THING);
match_possession();
match_here();
match_exit();
if(Wizard(player)) {
match_player();
match_absolute();
}
if ((thing = noisy_match_result()) == NOTHING)
return;
if (!*newobj || !strcasecmp(newobj, "me")) {
owner = player;
} else {
if ((owner = lookup_player(newobj)) == NOTHING) {
notify(player, "I couldn't find that player.");
return;
}
}
if (Typeof(thing) == TYPE_PLAYER && !God(player)) {
notify(player, "Players always own themselves.");
return;
}
/* in order to @chown an object, must fit one of the following:
*
* 1. player is a wizard
* 2. player owns the thing or controls the owner of the thing
* 3. thing is CHOWN_OK, and the player is holding the object.
*
* The player must also control the person who is receiving
* ownership of the object.
*
* There is another possibility: chowning to a Zone Master. In
* this case the player still has to own the thing or have it
* CHOWN_OK, but only needs to pass the enter (control) lock of
* the Zone Master. This is automatically covered by the controls
* check, though. We do have to check for getting stuff out of a
* ZoneMaster's ownership, though.
*
*/
if (!(Wizard(player) ||
((Owns(player, thing) ||
((Flags(thing) & CHOWN_OK) &&
((Typeof(thing) != TYPE_THING) || (Location(thing) == player))) ||
(ZMaster(Owner(thing)) &&
eval_boolexp(player, Enterkey(Owner(thing)), thing,
0, ENTERLOCK))) &&
controls(player, owner)))) {
notify(player, "Permission denied.");
return;
}
/* chowns on the zone master don't count towards fees */
if (!ZMaster(owner) && !ZMaster(Owner(thing))) {
if (!can_pay_fees(player, OBJECT_COST)) /* not enough money or quota */
return;
giveto(Owner(thing), OBJECT_COST);
#ifdef QUOTA
change_quota(Owner(thing), QUOTA_COST);
#endif
}
if (God(player)) {
Owner(thing) = owner;
} else {
Owner(thing) = Owner(owner);
}
Zone(thing) = Zone(owner);
Flags(thing) &= ~CHOWN_OK;
Flags(thing) &= ~WIZARD;
#ifdef ROYALTY_FLAG
Flags(thing) &= ~ROYALTY;
#endif
Flags(thing) &= ~INHERIT;
Flags(thing) |= HALT;
Powers(thing) = 0; /* wipe out all powers */
notify(player, "Owner changed.");
}
void do_chzone(player, name, newobj)
dbref player;
const char *name;
const char *newobj;
{
dbref thing;
dbref zone;
init_match(player, name, NOTYPE);
match_nearby();
if ((thing = noisy_match_result()) == NOTHING)
return;
if (!strcasecmp(newobj, "none"))
zone = NOTHING;
else {
init_match(player, newobj, NOTYPE);
match_here();
match_neighbor();
match_possession();
match_absolute();
if ((zone = noisy_match_result()) == NOTHING)
return;
if ((Typeof(zone) != TYPE_THING)
#ifdef DO_GLOBALS
&& (Typeof(zone) != TYPE_ROOM)
#endif
) {
notify(player, "Invalid zone object type.");
return;
}
}
/* we do use ownership instead of control as a criterion because
* we only want the owner to be able to rezone the object. Also,
* this allows players to @chzone themselves to an object they own.
*/
if (!Wizard(player) && !Owns(player, thing)) {
notify(player, "You don't have the power to shift reality.");
return;
}
/* a player may change an object's zone to NOTHING or to an object he owns */
if ((zone != NOTHING) && !Wizard(player) &&
!Owns(player, zone)) {
notify(player, "You cannot move that object to that zone.");
return;
}
/* only rooms may be zoned to other rooms */
if ((zone != NOTHING) &&
(Typeof(zone) == TYPE_ROOM) && Typeof(thing) != TYPE_ROOM) {
notify(player, "Only rooms may have parent rooms.");
return;
}
/* everything is okay, do the change */
db[thing].zone = zone;
if (Typeof(thing) != TYPE_PLAYER) {
/* if the object is a player, resetting these flags is rather
* inconvenient -- although this may pose a bit of a security
* risk. Be careful when @chzone'ing wizard or royal players.
*/
Flags(thing) &= ~WIZARD;
#ifdef ROYALTY_FLAG
Flags(thing) &= ~ROYALTY;
#endif
Flags(thing) &= ~INHERIT;
Powers(thing) = 0; /* wipe out all powers */
}
notify(player, "Zone changed.");
}
void do_attrib_flags(player, obj, atrname, flag)
dbref player;
char *obj;
char *atrname;
char *flag;
{
dbref thing;
ATTR *attrib;
char *p;
int f;
if ((thing = match_controlled(player, obj)) == NOTHING)
return;
if (!flag || !*flag) {
notify(player, "What flag do you want to set?");
return;
}
/* move past NOT token if there is one */
for (p = flag; *p && ((*p == NOT_TOKEN) || isspace(*p)); p++)
;
if (string_prefix("visual", p))
f = AF_ODARK;
else if (string_prefix("mortal_dark", p) && Hasprivs(player))
f = AF_MDARK;
else if (string_prefix("wizard", p) && Hasprivs(player))
f = AF_WIZARD;
else if (string_prefix("no_command", p))
f = AF_NOPROG;
else if (string_prefix("no_inherit", p))
f = AF_PRIVATE;
else if (string_prefix("no_clone", p))
f = AF_NOCOPY;
else {
notify(player, "Unrecognized attribute flag.");
return;
}
/* find our attribute. Don't need to check permissions to set it, since
* we really can't do any harm even if the attribute is locked.
*/
attrib = atr_get_noparent(thing, upcasestr(atrname));
if (!attrib) {
notify(player, "No such attribute to set.");
return;
}
if (f == AF_ODARK) {
if (*flag == NOT_TOKEN)
attrib->flags |= f;
else
attrib->flags &= ~f;
} else {
if (*flag == NOT_TOKEN)
attrib->flags &= ~f;
else
attrib->flags |= f;
}
notify(player, tprintf("%s - Set.", Name(thing)));
}
void do_set(player, name, flag)
dbref player;
const char *name;
const char *flag;
{
dbref thing;
int res, her, listen;
char *p;
char tbuf1[BUFFER_LEN];
/* check for attribute flag set first */
if ((p = (char *) index(name, '/')) != NULL) {
*p++ = '\0';
do_attrib_flags(player, name, p, flag);
return;
}
/* find thing */
if ((thing = match_controlled(player, name)) == NOTHING)
return;
if (God(thing) && !God(player)) {
notify(player, "Only God can set himself!");
return;
}
#ifdef INHERIT_FLAG
if (!Inherit(player) && Inherit(thing)) {
notify(player, "Authorization failed.");
return;
}
#endif
#ifdef DESTROY
/*
* The GOING flag can only be affected by set in one special case--A
* room that is set to be destroy may be saved.
*/
if (string_prefix("!GOING", flag) &&
(Typeof(thing) == TYPE_ROOM) && (Flags(thing) & GOING)) {
Flags(thing) &= ~GOING;
if (Owner(thing) > 0)
notify(Owner(thing),
"Your room has been spared from destruction.");
return;
}
#endif /* DESTROY */
her = Hearer(thing);
listen = Listener(thing);
/* check for attribute set first */
if ((p = (char *) index(flag, ':')) != NULL) {
ATTR *attrb = NULL;
ATTR *a = NULL;
*p++ = '\0';
/* check for predefined attribute match */
attrb = atr_match(upcasestr(flag));
/* check for _. This is an attribute copy. */
if (*p == '_') {
dbref thing1;
char *q;
q = (char *) index(p, '/');
if (! (q && *q)) {
notify(player, "I need an object and an attribute.");
return;
}
*q++ = '\0';
init_match(player, p + 1, NOTYPE); /* not p. Name shouldn't have to
* to start with an underscore.
*/
match_everything();
if ((thing1 = noisy_match_result()) == NOTHING)
return;
if ((a = atr_get_noparent(thing1, upcasestr(q))) == NULL) {
notify(player, "No such attribute.");
return;
}
strcpy(tbuf1, uncompress(a->value));
} else {
strcpy(tbuf1, p);
}
if (attrb) {
if (!strcmp(attrb->name, "ALIAS")) {
do_alias(player, thing, attrb, tbuf1);
return;
}
if (!Can_Write_Attr(player, thing, attrb)) {
notify(player, "Sorry, you cannot modify that.");
return;
}
res = atr_add(thing, attrb->name, tbuf1, player, attrb->flags);
if (!res) {
notify(player, "No such attribute to reset.");
return;
}
if (res == -1) {
notify(player, "That attribute cannot be changed by you.");
return;
}
} else {
res = atr_add(thing, upcasestr(flag), tbuf1, player, NOTHING);
if (!res) {
notify(player, "No such attribute to reset.");
return;
}
if (res == -1) {
notify(player, "That attribute cannot be changed by you.");
return;
}
}
/* one special case for listen */
if (attrb && !strcmp(attrb->name, "LISTEN")) {
if (GoodObject(Location(thing))) {
if (!*p && !listen && !Hearer(thing)) {
notify_except(Contents(Location(thing)), thing,
tprintf("%s loses its ears and becomes deaf.",
Name(thing)));
} else if (*p && !her && !listen)
notify_except(Contents(Location(thing)), thing,
tprintf("%s grows ears and can now hear.",
Name(thing)));
}
}
/* automatically set the STARTUP flag if appropriate */
if (attrb && !strcmp(attrb->name, "STARTUP")) {
if (*p)
Flags(thing) |= STARTUP;
else
Flags(thing) &= ~STARTUP;
}
if (!Quiet(player) && !Quiet(thing))
notify(player, tprintf("%s - Set.", Name(thing)));
return;
}
/* we haven't set an attribute, so we must be setting a flag */
/* move p past NOT_TOKEN if present */
for (p = (char *) flag; *p && (*p == NOT_TOKEN || isspace(*p)); p++) ;
/* identify flag */
if (*p == '\0') {
notify(player, "You must specify a flag to set.");
return;
}
set_flag(player, thing, p, (*flag == NOT_TOKEN) ? 1 : 0, her, listen);
}
void do_cpattr(player, oldpair, newpair)
dbref player;
char *oldpair;
char *newpair[];
{
/* the command is of the format:
* @cpattr oldobj/oldattr = newobj1/newattr1, newobj2/newattr2, etc.
*/
dbref oldobj;
char tbuf1[BUFFER_LEN];
int i;
char *p;
ATTR *a;
char *text;
/* must copy from something */
if (!oldpair || !*oldpair) {
notify(player, "What do you want to copy from?");
return;
}
/* find the old object */
strcpy(tbuf1, oldpair);
p = (char *) index(tbuf1, '/');
if (!p || !*p) {
notify(player, "What object do you want to copy the attribute from?");
return;
}
*p++ = '\0';
init_match(player, tbuf1, NOTYPE);
match_everything();
oldobj = noisy_match_result();
if (oldobj == NOTHING)
return;
/* find the old attribute */
a = atr_get_noparent(oldobj, upcasestr(p));
if (!a) {
notify(player, "No such attribute to copy from.");
return;
}
/* check permissions to get it */
if (!Can_Read_Attr(player, oldobj, a)) {
notify(player, "Permission to read attribute denied.");
return;
}
/* we can read it. Copy the value. */
text = safe_uncompress(a->value);
/* now we loop through our new object pairs and copy, calling @set. */
for (i = 1; i < MAX_ARG && (newpair[i] != NULL); i++) {
if (!*newpair[i]) {
notify(player, "What do you want to copy to?");
} else {
strcpy(tbuf1, newpair[i]);
p = (char *) index(tbuf1, '/');
if (!p || !*p) {
notify(player, "What object do you want to copy the attribute to?");
} else {
*p++ = '\0';
do_set(player, tbuf1, tprintf("%s:%s", p, text));
}
}
}
free(text); /* safe_uncompress malloc()s memory */
notify(player, "Attributes copied.");
}
void do_gedit(player, it, argv)
dbref player;
char *it;
char *argv[];
{
ALIST *a;
dbref thing;
char tbuf1[BUFFER_LEN];
char *p, *q;
ATTR *attrib;
int is_wild = 0;
if(!(it && *it)) {
notify(player, "I need to know what you want to edit.");
return;
}
strcpy(tbuf1, it);
q = (char *) index(tbuf1, '/');
if (!(q && *q)) {
notify(player, "I need to know what you want to edit.");
return;
}
*q++ = '\0';
init_match(player, tbuf1, NOTYPE);
match_everything();
thing = noisy_match_result();
if ((thing == NOTHING) || !controls(player, thing)) {
notify(player, "Permission denied.");
return;
}
if(*q == '_') q++;
if (!argv[1] || !*argv[1]) {
notify(player, "Nothing to do.");
return;
}
/* first let's check for wildcard characters */
for (p = q; *p && !is_wild; p++)
if ((*p == '*') || (*p == '?'))
is_wild = 1;
if (!is_wild) {
/* we only have one attribute. Check for possible abbreviation,
* then edit that the attribute with that name.
*/
attrib = atr_match(upcasestr(q));
if (attrib)
do_edit(player, thing, attrib->name, argv);
else
do_edit(player, thing, q, argv);
} else {
/* we've got a wildcard, treat like old @gedit */
for(a = db[thing].list; a; a = AL_NEXT(a))
if(!AL_BAD(a) && wild_match(q, AL_NAME(a)))
do_edit(player, thing, AL_NAME(a), argv);
}
}
void do_edit(player, thing, q, argv)
dbref player;
dbref thing;
char *q; /* attribute name */
char *argv[];
{
int d, len, res;
ATTR *a;
char *r, *s , *val;
char tbuf1[BUFFER_LEN];
val = argv[1];
r = (argv[2]) ? argv[2] : (char *) "";
a = atr_get_noparent(thing, q);
if(!a) {
notify(player, "No such attribute, try set instead.");
return;
}
if ((a->flags & AF_LOCKED) && (Owner(player) != Owner(a->creator))) {
notify(player, "You need to control an attribute to edit it.");
return;
}
s = (char *) uncompress(a->value); /* warning: pointer to static buffer */
if (!strcmp(val, "$")) {
/* append */
if (strlen(s) + strlen(r) < BUFFER_LEN) {
strcpy(tbuf1, s);
strcat(tbuf1, r);
}
} else if (!strcmp(val, "^")) {
/* prepend */
if (strlen(s) + strlen(r) < BUFFER_LEN) {
strcpy(tbuf1, r);
strcat(tbuf1, s);
}
} else {
/* find and replace */
len = strlen(val);
for (d = 0; (d < BUFFER_LEN) && *s;)
if (strncmp(val, s, len) == 0) {
if ((d + strlen(r)) < BUFFER_LEN) {
strcpy(tbuf1 + d, r);
d += strlen(r);
s += len;
} else
tbuf1[d++] = *s++;
} else
tbuf1[d++] = *s++;
tbuf1[d++] = 0;
}
res = atr_add(thing, a->name, tbuf1, player, NOTHING);
if(!res) {
notify(player, "That attribute seems to have vanished!");
return;
}
if(res == -1) {
notify(player, "You don't have the power to change that.");
return;
}
if(!Quiet(player) && !Quiet(thing))
notify(player, tprintf("%s - Set: %s", a->name, tbuf1));
}
void do_trigger(player, object, argv)
dbref player;
char *object;
char *argv[];
{
dbref thing;
int a;
char *s;
char tbuf1[BUFFER_LEN];
strcpy(tbuf1, object);
for(s = tbuf1; *s && (*s != '/'); s++);
if(!*s) {
notify(player, "I need to know what attribute to trigger.");
return;
}
*s++ = '\0';
init_match(player, tbuf1, NOTYPE);
match_everything();
thing = noisy_match_result();
if(thing == NOTHING) return;
if (!controls(player, thing)) {
notify(player, "Permission denied.");
return;
}
if (God(thing) && !God(player)) {
notify(player, "You can't trigger God!");
return;
}
#ifdef INHERIT_FLAG
if ((!Inherit(player) && Inherit(thing)) && !LinkOk(thing)) {
notify(player, "Authorization failed.");
return;
}
#endif
/* trigger modifies the stack */
for (a = 0; a < 10; a++)
wptr[a] = argv[a + 1];
/* we need to call did_it because trigger uses a charge */
did_it(player, thing, NULL, NULL, NULL, NULL, upcasestr(s), NOTHING);
if(!Quiet(player) && !Quiet(thing))
notify(player, tprintf("%s - Triggered.", Name(thing)));
}
/* for lack of a better place, the use code is here */
void do_use(player, what)
dbref player;
const char *what;
{
dbref thing;
/* find it */
init_match(player, what, TYPE_THING);
match_near_things();
/* if we pass the use key, do it */
if ((thing = noisy_match_result()) != NOTHING) {
if (!eval_boolexp(player, db[thing].usekey, thing, 0, USELOCK)) {
notify(player, "Permission denied.");
return;
} else
did_it(player, thing, "USE", "Used.", "OUSE", NULL, "AUSE", NOTHING);
}
}
void do_parent(player, name, parent_name)
dbref player;
char *name;
char *parent_name;
{
dbref thing;
dbref parent;
dbref check;
int i;
init_match(player, name, NOTYPE);
match_nearby();
if ((thing = noisy_match_result()) == NOTHING)
return;
/* players may not be parented */
if (Typeof(thing) == TYPE_PLAYER) {
notify(player, "Don't you like your biological parents?");
return;
}
if (!parent_name || !*parent_name || !strcasecmp(parent_name, "none"))
parent = NOTHING;
else {
init_match(player, parent_name, NOTYPE);
match_everything();
if ((parent = noisy_match_result()) == NOTHING)
return;
}
/* do control check */
if (!controls(player, thing)) {
notify(player, "Permission denied.");
return;
}
/* a player may change an object's parent to NOTHING or to an
* object he owns, or one that is LINK_OK.
*/
if ((parent != NOTHING) && !Wizard(player) &&
!Owns(player, parent) && !LinkOk(parent)) {
notify(player, "Permission denied.");
return;
}
/* check to make sure no recursion can happen */
if (parent == thing) {
notify(player, "A thing cannot be its own ancestor!");
return;
}
if (parent != NOTHING) {
for (i = 0, check = Parent(parent);
(i < MAX_PARENTS) && (check != NOTHING);
i++, check = Parent(check)) {
if (check == thing) {
notify(player, "You are not allowed to be your own ancestor!");
return;
}
}
if (i >= MAX_PARENTS) {
notify(player, "Too many ancestors.");
return;
}
}
/* everything is okay, do the change */
db[thing].parent = parent;
notify(player, "Parent changed.");
}
void do_wipe(player, name)
dbref player;
char *name;
{
/* obliterate all attribute from an object */
dbref thing;
ALIST *a;
init_match(player, name, NOTYPE);
match_nearby();
if ((thing = noisy_match_result()) == NOTHING)
return;
/* this is too destructive of a command to be used by someone who
* doesn't own the object. Thus, the check is on Owns not controls.
*/
if (!Wizard(player) && !Owns(player, thing)) {
notify(player, "Permission denied.");
return;
}
/* protect SAFE objects */
if (Safe(thing)) {
notify(player, "That object is protected.");
return;
}
/* for added security, only God can modify wiz-only-modifiable
* attributes using his command. Also, you cannot wipe attributes
* that you do not control.
*/
for (a = db[thing].list; a; a = AL_NEXT(a)) {
if (AL_BAD(a) ||
((AL_FLAGS(a) & AF_WIZARD) && !God(player)) ||
((AL_FLAGS(a) & AF_LOCKED) &&
(Owner(player) != Owner(AL_CREATOR(a)))))
continue;
atr_add(thing, AL_NAME(a), "", player, NOTHING);
}
notify(player, "Attributes wiped.");
}